package top.ucat.boots.starter.oauth2.server.factory;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import top.ucat.boots.common.check.Assert;
import top.ucat.boots.common.exception.BaseException;
import top.ucat.boots.starter.db.annotation.Db;
import top.ucat.boots.starter.oauth2.client.beans.oauth.*;
import top.ucat.boots.starter.oauth2.client.beans.oauth.login.QRLoginDto;
import top.ucat.boots.starter.oauth2.client.definition.UserCodeTypeDefinition;
import top.ucat.boots.starter.oauth2.client.entity.OauthClientDetails;
import top.ucat.boots.starter.oauth2.client.entity.OauthUserCredentials;
import top.ucat.boots.starter.oauth2.client.realm.AuthorizingRealm;
import top.ucat.boots.starter.oauth2.client.service.api.ClientService;
import top.ucat.boots.starter.oauth2.client.service.api.TokenService;
import top.ucat.boots.starter.oauth2.server.dao.OauthUserCredentialsDao;
import top.ucat.boots.starter.oauth2.server.factory.base.LoginFactory;
import top.ucat.boots.starter.oauth2.server.utils.KeysUtil;

/**
 * @Auther: Jun
 * @Date: 2019/9/3 18:17
 * @Description:
 */
@Slf4j
public class DefaultLoginFactory implements LoginFactory {


    private RedisTemplate redisTemplate;
    private OauthUserCredentialsDao oauthUserCredentialsDao;

    private AuthorizingRealm authorizingRealm;

    private TokenService tokenService;

    private ClientService clientService;

    private static DefaultLoginFactory instanc;

    public void setAuthorizingRealm(AuthorizingRealm authorizingRealm) {
        this.authorizingRealm = authorizingRealm;
    }

    public void setTokenService(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    public void setClientService(ClientService clientService) {
        this.clientService = clientService;
    }


    private DefaultLoginFactory(RedisTemplate redisTemplate, OauthUserCredentialsDao oauthUserCredentialsDao) {
        this.redisTemplate = redisTemplate;
        this.oauthUserCredentialsDao = oauthUserCredentialsDao;
    }

    public static DefaultLoginFactory getInstance() {
        return instanc;
    }

    public static DefaultLoginFactory getInstance(RedisTemplate redisTemplate, OauthUserCredentialsDao oauthUserCredentialsDao) {
        //单例扫码登录工厂
        if (instanc == null) {
            synchronized (DefaultLoginFactory.class) {
                if (instanc == null) {
                    instanc = new DefaultLoginFactory(redisTemplate, oauthUserCredentialsDao);
                }
            }
        }
        return instanc;
    }

    @Override
    public OauthUserCredentials getUserCredentials(String userCode, String userCodeType, String systemType) {
        OauthUserCredentials credential = oauthUserCredentialsDao.getOauthUserCredential(userCode, userCodeType, systemType);
        return credential;
    }

    @Override
    public OauthUserCredentials registerUserCredentials(String userId, String userCode, String userCodeType, String systemType) {
        return registerUserCredentials(userId, userCode, userCodeType, systemType, true);
    }

    @Override
    public OauthUserCredentials registerUserCredentials(String userId, String userCode, String userCodeType, String systemType, boolean isCheck) {
        OauthUserCredentials credential = null;
        if (isCheck) {
            credential = this.getUserCredentials(userCode, userCodeType, systemType);
        }
        if (credential == null) {
            if (StringUtils.isEmpty(userId)) {
                throw new BaseException("提供用户的UserId用于注册", 400);
            }
            credential = new OauthUserCredentials();
            credential.setUserId(userId);
            credential.setUserCode(userCode);
            credential.setUserCodeType(userCodeType);
            credential.setSystemType(systemType);
            int i = oauthUserCredentialsDao.saveOauthUserCredential(credential);
            if (i > 0) {
                redisTemplate.boundHashOps(OauthRedisKey.OAUTH_USER_CREDENTIALS).delete(KeysUtil.getUserSystemKey(userCode, userCodeType, systemType));
                return credential;
            }
        }
        return credential;
    }

    @Override
    public Object registerUser(String userId, String userCode, String userCodeType, String systemType) {
        return null;
    }


    public OauthToken login(OauthTokenDto dto) {
        OauthToken accessToken = tokenService.getPasswordAccessToken(dto);
        return accessToken;
    }
}
